package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.app.mq.MovementMQManager;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.Announcement;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.domain.vo.*;
import com.itheima.service.db.AnnouncementService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.DateFormatUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class MovementManager {

    @Reference
    private MovementService movementService;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    /**
     * 发布我的动态
     * @param movement   动态对象
     * @param imageContent 图片 存储到阿里云的平台
     */
    public void addMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //保存我的动态-封装movement对象
        List pathList = new ArrayList<>();
        if(imageContent!=null){ //图片不为空上传
            for (MultipartFile file : imageContent) {
                String uploadPath = "https://"+ ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
                pathList.add(uploadPath);
            }
        }

        //自己生成一个 ObjectId
        ObjectId objectId = ObjectId.get();
        movement.setId( objectId );
        //创建即将保存的movement 动态对象  构建对象保存
        movement.setUserId(UserHolder.getId());
        //mongo中的id 是一个随机字符串  不是数字类型  , 但是大数据平台以后要给咱们推荐数据的时候 需要是数字id
        //自己创建一个字段 作为给大数据平台使用的数字id
        //movement.setPid(1L);//TODO 目前写死 推荐的id字段 大数据平台使用
        movement.setMedias(pathList);//添加所有的图片路径集合
        movement.setState(0); //TODO 动态审核状态 现阶段写死 为1 要改
        //movement.setCreated(System.currentTimeMillis());  提供者端设置时间
        movement.setSeeType(1);//默认公开 咱们探花中没有此功能
        movementService.saveMovement(movement);

        System.out.println("------------->>>>>>>>>>>"+movement.getId());
        //发送mq消息
        rocketMQTemplate.convertAndSend("tanhua-movement-161" , movement.getId().toHexString());

        //发布动态
        movementMQManager.sendMsg( movement.getId().toHexString()  , MovementMQManager.MOVEMENT_PUBLISH);
    }

    @Reference
    private UserInfoService userInfoService;
    /**
     * 根据用户的id查询用户动态 - 我的动态
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    public PageBeanVo findMovementByUserId(Integer page, Integer pageSize, Long userId) {
        //1.分页查询我的动态  new PageBeanVo(page , pageSize , counts ,  movementList);
        PageBeanVo pageBeanVo = movementService.findMovementByUserId(page , pageSize , userId);

        //2.将返回值替换成页面所需要的返回值  数据搬家
        //2.1 创建页面所需要的返回对象
        List<MovementVo> voList = new ArrayList<>();
        //2.2. 数据库返回的数据
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //2.3 数据转换
        if(CollectionUtil.isNotEmpty(items)){
            for (Movement movement : items) {//动态详情数据
                //3.1 构建每一个vo对象
                MovementVo vo = new MovementVo();
                //3.2 动态数据
                //3.3 用户数据
                UserInfo userInfo = userInfoService.findById(movement.getUserId());

                //3.4 数据封装
                //3.4.1 能够匹配上的字段 自动封装  先封装用户信息  再封装动态(有可能字段会重复 重复字段会覆盖掉)
                BeanUtil.copyProperties(userInfo , vo);
                BeanUtil.copyProperties(movement , vo);
                //3.4.2 手动封装(匹配不上的字段)
                if(StrUtil.isNotEmpty( userInfo.getTags() )){
                    vo.setTags( userInfo.getTags().split(",") );//赋值标签
                }
                if(CollectionUtil.isNotEmpty(movement.getMedias())){
                    vo.setImageContent( movement.getMedias().toArray(new String[]{}) );//设置图片
                }
                vo.setDistance("3.2公里"); //TODO 暂时写死
                /*Date date = new Date(movement.getCreated());
                String format = DateFormatUtil.format(date);
                vo.setCreateDate(format);*/
                vo.setCreateDate(DateFormatUtil.format( new Date(movement.getCreated()) ));
                //是否点赞和是否喜欢 下一天的代码(暂时写死)

                //将vo放入集合
                voList.add(vo);
            }
        }


        //重新赋值展示的数据 -> 前端要的数据 动态+用户
        pageBeanVo.setItems(voList);
        //返回数据
        return pageBeanVo;
    }

    /**
     * 查询好友的动态
     *  //1.获得当前用户id
     *  //2.根据当前用户id 查询用户的朋友圈数据
     *  //3.数据转换
     *  //4.封装pageBeanVo
     *  //5.返回
     * @param page
     * @param pageSize
     * @return
     */
    public PageBeanVo findFriendMovement(Integer page, Integer pageSize) {
        //1.获得当前用户id
        Long loginUserId = UserHolder.getId();
        //2.根据当前用户id 查询用户的朋友圈数据
        PageBeanVo pageBeanVo = movementService.findFriendMovement(page , pageSize ,loginUserId );
        //3.数据转换
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();

        //数据搬家
        if(CollectionUtil.isNotEmpty( items )){
            for (Movement movement : items) {
                //构建返回值
                MovementVo vo = new MovementVo();
                //查询出用户的数据
                UserInfo userInfo = userInfoService.findById(movement.getUserId()); //传入的发布动态人的id
                //封装数据
                vo.setUserInfo(userInfo);
                vo.setMovement(movement);
                //放入集合
                movementVoList.add(vo);
            }
        }

        //4.封装pageBeanVo
        pageBeanVo.setItems(movementVoList);
        //5.返回
        return pageBeanVo;
    }

    /**
     * 查询推荐动态
     * @param page
     * @param pageSize
     * @return
     */
    public PageBeanVo findRecommendMovement(Integer page, Integer pageSize) {
        //1.获得当前用户id
        Long loginUserId = UserHolder.getId();
        //2.调用查询
        PageBeanVo pageBeanVo = movementService.findRecommendMovement(page,  pageSize , loginUserId);
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();
        //3.封装结果 - 数据搬家
        if(CollectionUtil.isNotEmpty(items)){
            for (Movement movement : items) {
                //3.1 根据每一个动态查询用户信息
                UserInfo userInfo  = userInfoService.findById(movement.getUserId());
                //3.2 封装数据
                MovementVo vo = new MovementVo();
                vo.setUserInfo(userInfo); //先setUserInfo 因为id字段会重复
                vo.setMovement(movement);

                //设置点赞和喜欢
                //方案1: 在此处可以再次查询mongo   方案2: 保存动态的时候 存入了缓存一份
                String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE ,loginUserId , movement.getId().toHexString() );
                Boolean flag = stringRedisTemplate.hasKey(key);
                if(flag){ //判断缓存中是否有对某个动态进行了点赞 如果有设置为1
                    vo.setHasLiked(1);
                }
                String key2 = StrUtil.format(ConstantUtil.MOVEMENT_LOVE ,loginUserId , movement.getId().toHexString() );
                Boolean flag2 = stringRedisTemplate.hasKey(key);
                if(flag2){ //判断缓存中是否有对某个动态进行了点赞 如果有设置为1
                    vo.setHasLoved(1);
                }
                //3.3 添加到集合
                movementVoList.add(vo);
            }
        }
        //4.返回数据
        pageBeanVo.setItems(movementVoList);
        return pageBeanVo;
    }


    @Reference
    private CommentService commentService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MovementMQManager movementMQManager;
    /**
     * 点赞
     * @param publishId
     * @return
     */
    public Integer commentLike(String publishId) {
        //获得当前登录人id
        Long loginUserId = UserHolder.getId();
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());//时间
        comment.setPublishId( new ObjectId(publishId));//转换publishId 动态id
        comment.setCommentType(ConstantUtil.MOVEMENT_LIKE_1); //对动态进行了点赞
        comment.setUserId( loginUserId ); //操作人
        //保存点赞操作
        Integer count = commentService.saveMovementComment(comment);

        //保存 谁对哪个动态进行了点赞
        //stringRedisTemplate.opsForValue().set( "commend_like_99_xxxx" , "1");
        //stringRedisTemplate.opsForValue().set( "commend_like_98_yyyy" , "1");
        //stringRedisTemplate.opsForValue().set( "commend_like_"+loginUserId+"_"+publishId , "1");
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE ,loginUserId , publishId );
        stringRedisTemplate.opsForValue().set( key , "1");

        //点赞
        movementMQManager.sendMsg( publishId  , MovementMQManager.MOVEMENT_LIKE);
        return count;
    }

    /**
     * 取消点赞
     * @param publishId
     * @return
     */
    public Integer commentDisLike(String publishId) {
        //获得当前登录人id
        Long loginUserId = UserHolder.getId();
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());//时间
        comment.setPublishId( new ObjectId(publishId));//转换publishId 动态id
        comment.setCommentType(ConstantUtil.MOVEMENT_LIKE_1); //对动态进行了点赞
        comment.setUserId( loginUserId ); //操作人
        //保存点赞操作
        Integer count = commentService.deleteMovementComment(comment);

        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE ,loginUserId , publishId );
        stringRedisTemplate.delete(key);

        //点赞
        movementMQManager.sendMsg( publishId  , MovementMQManager.MOVEMENT_DISLIKE);
        return count;
    }

    //动态喜欢
    public Integer saveMovementLove(String movementId) {
        //1. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(3);
        comment.setUserId(UserHolder.get().getId());

        //2. 调用service进行点赞
        Integer num = commentService.saveMovementComment(comment);

        //3. 向redis中保存点赞标识
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, UserHolder.get().getId(), movementId), "1");

        //4. 返回点赞数量
        return num;
    }

    //动态取消喜欢
    public Integer deleteMovementLove(String movementId) {
        //1. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(3);
        comment.setUserId(UserHolder.get().getId());

        //2. 调用service进行取消点赞
        Integer num = commentService.deleteMovementComment(comment);

        //3. 从redis中删除点赞标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, UserHolder.get().getId(), movementId));

        //4. 返回点赞数量
        return num;
    }

    /**
     * 单条动态
     * @param movementId
     * @return
     */
    public MovementVo findMovementVo(String movementId) {
        //1.查询到动态详情信息
        Movement movement = movementService.findMovementByMovementId(movementId);

        //2.根据动态详情信息 查询用户对象
        UserInfo userInfo = userInfoService.findById(movement.getUserId());
        //3.封装vo
        MovementVo vo = new MovementVo();
        vo.setUserInfo(userInfo);
        vo.setMovement(movement);

        //查询动态
        movementMQManager.sendMsg( movementId  , MovementMQManager.MOVEMENT_BROWSE);
        return vo;
    }

    /**
     * 查询评论列表
     * @param page
     * @param pageSize
     * @param movementId
     * @return
     */
    public PageBeanVo findCommentList(Integer page, Integer pageSize, String movementId) {
        //1.根据动态的id 查询评论的分页数据
        PageBeanVo pageBeanVo = commentService.findCommentList(page , pageSize , movementId);

        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> voList = new ArrayList<>();

        //2.查询用户信息
        if(CollectionUtil.isNotEmpty( items )){
            for (Comment comment : items) {//循环数据
                UserInfo userInfo = userInfoService.findById(comment.getUserId());//查询评论人的用户数据
                //构建对象
                CommentVo commentVo = new CommentVo();
                //赋值
                BeanUtil.copyProperties(userInfo , commentVo);
                BeanUtil.copyProperties(comment , commentVo);
                commentVo.setCreateDate( DateFormatUtil.format(new Date(comment.getCreated()))  );

                String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE ,UserHolder.getId(), comment.getId() );
                Boolean flag = stringRedisTemplate.hasKey(key);
                if(flag){ //判断缓存中是否有对某个动态进行了点赞 如果有设置为1
                    commentVo.setHasLiked(1);
                }
                //放入集合
                voList.add(commentVo);
            }
        }
        //3.封装vo
        pageBeanVo.setItems(voList);
        return pageBeanVo;
    }

    /**
     * 发表评论
     * @return
     */
    public Integer saveComment(String movementId, String text) {
        //获得当前登录人id
        Long loginUserId = UserHolder.getId();
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());//时间
        comment.setPublishId( new ObjectId(movementId));//转换publishId 动态id
        comment.setCommentType(ConstantUtil.MOVEMENT_LIKE_2); //对动态进行了点赞
        comment.setContent(text); //评论的内容
        comment.setUserId( loginUserId ); //操作人
        //保存评论操作
        Integer count = commentService.saveMovementComment(comment);

        //评论动态
        movementMQManager.sendMsg( movementId  , MovementMQManager.MOVEMENT_COMMENT);
        return count;
    }

    /**
     * 展示喜欢 , 评论 , 点赞的方法
     * @param page
     * @param pageSize
     * @param commentType
     * @return
     */
    public PageBeanVo messagesByCommentType(Integer page, Integer pageSize, int commentType) {
        //查询到分页数据
        PageBeanVo pageBeanVo = commentService.findMessagesByCommentType(page , pageSize , commentType ,UserHolder.getId());

        //封装数据
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<UserCommentVo> voList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(items)){
            for (Comment comment : items) {
                //查询userInfo的信息
                UserInfo userInfo = userInfoService.findById(comment.getUserId());
                //创建需要封装的vo对象
                UserCommentVo vo  = new UserCommentVo();
                BeanUtil.copyProperties(userInfo , vo);
                //转换日期
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                vo.setCreateDate( simpleDateFormat.format(userInfo.getCreated())  );
                //加入集合
                voList.add(vo);
            }
        }
        //返回vo
        pageBeanVo.setItems( voList );
        return pageBeanVo;
    }

    //动态评论点赞
    public Integer movementCommentLike(String commentId) {

        Long userId = UserHolder.getId();

        //创建对象
        Comment comment=new Comment();
        comment.setPublishId(new ObjectId(commentId));
        comment.setCommentType(6);
        comment.setUserId(userId);

        Integer countLike = commentService.saveCommentLike(comment);

        //存入缓存
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), commentId), "6");
        return countLike;

    }

    //动态评论取消点赞
    public Integer movementCommentdisLike(String commentId) {

        Long userId = UserHolder.getId();

        Comment comment=new Comment();
        comment.setPublishId(new ObjectId(commentId));
        comment.setCommentType(6);
        comment.setUserId(userId);

        Integer countLike = commentService.deleteCommentLike(comment);

        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), commentId));


        return countLike ;

    }

    /*
     *
     *  公告列表
     * @param page
     * @param pageSize
     * @author
     * @date
     * @return com.itheima.domain.vo.PageBeanVo
     */

    @Reference
    private AnnouncementService announcementService;

    public PageBeanVo messagesAnnouncements(Integer pageNum, Integer pageSize) {
        //查询出所有的公告通知封装到了PageBeanVo
        PageBeanVo pageBeanVo= announcementService.findAll(pageNum,pageSize);

        List<Announcement> items = (List<Announcement>) pageBeanVo.getItems();

        //Vo
        List<AnnouncementVo> announcementVoList=new ArrayList<>();

        if (CollectionUtil.isNotEmpty(items)){

            for (Announcement announcement : items) {
                //封装数据
                AnnouncementVo announcementVo = new AnnouncementVo();
                //Id
                announcementVo.setId(announcement.getId()+"");
                //公告标题
                announcementVo.setTitle(announcement.getTitle());
                //公告内容
                announcementVo.setDescription(announcement.getDescription());

                //转换日期
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                announcementVo.setCreateDate( simpleDateFormat.format(announcement.getCreated())  );
                announcementVoList.add(announcementVo);
            }



        }

        pageBeanVo.setItems(announcementVoList);
        return pageBeanVo;
    }
}
